Thread: [HELP] With College Assignment

  1. #1
    Registered User
    Join Date
    Nov 2015
    Posts
    9

    [HELP] With College Assignment

    The assignment is to Get User input for Names, Ages and State of residence. Then Output average age of the group plus a list of names of people from Texas. Average Age easily solved, my problem is collecting the names then printing the output.

    My output according to GeeksforgeeksIDE is:
    members from TX are (null)
    members from TX are a
    members from TX are

    Any Advice?

    Code:
    #include <stdio.h>
    #include <string.h>
    int main() 
    {
        int fam_size=0;
        int i=0;
        int j=0;
        int txCnt=0;
        
        char state[2];
        char tempName[50];
        
        /* generate array of strings the size of family */
        printf("How large is your Family: ");
        scanf("%d", &fam_size);
        char *namesTx[fam_size];
        
        for(i=0; i<fam_size; i++){
            printf("\nEnter your family member's name: ");
            fgets(tempName, 50, stdin);
            printf("\nWhat state is s/he from? (use postal abbr) ");
            fgets(state, 2, stdin);
            /* saves names of family members from TX only */
            if(state == "TX"){
                strcpy (namesTx, tempName);
                txCnt++;
            }
        }
        for(j=0; j<fam_size; j++){
            printf("\nmembers from TX are %s", namesTx[j]);
        }
    }

  2. #2
    Registered User
    Join Date
    May 2010
    Posts
    4,631
    Let's start with the following snippet:

    Code:
       char state[2];
        char tempName[50];
         
        /* generate array of strings the size of family */
        printf("How large is your Family: ");
        scanf("%d", &fam_size);
        char *namesTx[fam_size];
    ...     
            printf("\nWhat state is s/he from? (use postal abbr) ");
            fgets(state, 2, stdin);
            /* saves names of family members from TX only */
            if(state == "TX"){
                strcpy (namesTx, tempName);
    First you declared state as an array of char of size 2. Do you realize that fgets() always reserves room for the end of string character. This means that your state variable only has room for one character. Also realize that if there is room in the array is large enough the end of line character is also part of the string. Your state string should have a size of at least 3, 4 would be preferable.

    Next where are you allocating memory for that pointer?

    Lastly be careful when switching between fgets() and scanf(), scanf() leaves the end of line character in the input buffer which can confuse fgets().

    Jim

  3. #3
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    [code]
    char *namesTx[fam_size]=malloc(20*sizeof(char))
    [\code]

  4. #4
    Registered User camel-man's Avatar
    Join Date
    Jan 2011
    Location
    Under the moon
    Posts
    693
    Take a look into this link on dynamically allocating array of strings in C

    How do I dynamically allocate an array of strings in C? - Stack Overflow
    Code:
    int get_random_number(void)
    {
       return 4; //chosen by fair dice roll.
                 //guaranteed to be random
    }

  5. #5
    Registered User
    Join Date
    Nov 2015
    Posts
    9

    Unhappy

    Alright after reading your suggestions and learning a lot more about pointers and memory allocation here is what I have. Now I am having issues with fgets running ahead (fixed fgets)... not getting expected outputs from the array outputs are blanks. This is really frustrating.

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    int main() 
    {
        int fam_size=0;
        int i=0;
        int j=0;
        int k=0;
        int txCnt=0;
        char ch;
        
        char state[4];
        char tempName[20];
        
        /* generate array of strings the size of family */
        printf("How large is your Family: ");
        scanf("%d", &fam_size);
        ch = getchar();
        char **namesTx=malloc(fam_size*sizeof(char *));
        for(k=0; k<fam_size; k++){
            namesTx[k]=malloc(20*sizeof(char *));
        }
    
    
        for(i=0; i<fam_size; i++){
            printf("\nEnter your family member's name: ");
            fgets(tempName, 20, stdin);
            ch=getchar();
            printf("\nWhat state is s/he from? (use postal abbr) ");
            fgets(state, 4, stdin);
            ch=getchar();
            /* saves names of family members from TX only */
            if(state == "TX"){
                strcpy (namesTx[txCnt], tempName);
                txCnt++;
            }
        }
        for(j=0; j<fam_size; j++){
            printf("\nmembers from TX are %s", namesTx[j]);
        }
        for(k=0; k<fam_size; k++){
            free(namesTx[k]);
        }
    }
    Last edited by Joshua Ray; 11-19-2015 at 03:34 AM. Reason: Fixed one problem myself

  6. #6
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    I messed around with my debugger (gdb) in Netbeans and watched tempName. It is getting the input from stdin. However it is not getting into namesTx. Is there something wrong with my implementation?
    Last edited by Joshua Ray; 11-19-2015 at 04:17 AM. Reason: a word

  7. #7
    Registered User camel-man's Avatar
    Join Date
    Jan 2011
    Location
    Under the moon
    Posts
    693
    Code:
    if(state == "TX"){
    In C you cannot compare strings in such a way. You need to use the string compare method in the String.h library.

    Something like


    Code:
    if(!strcmp(state,"TX")){
    Last edited by camel-man; 11-19-2015 at 08:19 AM.
    Code:
    int get_random_number(void)
    {
       return 4; //chosen by fair dice roll.
                 //guaranteed to be random
    }

  8. #8
    Registered User
    Join Date
    May 2010
    Posts
    4,631
    Also remember that state will contain the end of line character '\n'.

    Jim

  9. #9
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    Quote Originally Posted by camel-man View Post
    Code:
    if(state == "TX"){
    In C you cannot compare strings in such a way. You need to use the string compare method in the String.h library.

    Something like


    Code:
    if(!strcmp(state,"TX")){

    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    void txFam(int size, char **names);
    
    
    int main() 
    {
        int fam_size=0;
        int i=0;
        int j=0;
        int k=0;
        char ch;
        
        /* generate array of strings the size of family */
        printf("How large is your Family: ");
        scanf("%d", &fam_size);
        ch = getchar();
        char **namesTx=malloc(fam_size*sizeof(char *));
        txFam(fam_size, namesTx);
        
        printf("Family Members from Texas are: ");
        for(j=0; j<fam_size; j++){
            printf("\n%s", namesTx[j]);
        }
        for(k=0; k<fam_size; k++){
            free(namesTx[k]);
        }
    }
    
    
    void txFam(int size, char **names)
    {
        int txCnt=0;
        char state[4];
        char tempName[20];
        
        for(int k=0; k<size; k++){
            names[k]=malloc(20*sizeof(char *));
        }
        
        for(int i=0; i<size; i++){
            printf("\nEnter your family member's name: ");
            fgets(tempName, 20, stdin);
    
    
            printf("\nWhat state is s/he from? (use postal abbr) ");
            fgets(state, 4, stdin);
            
            /* saves names of family members from TX only */
            if( (strcmp(state,"TX")) == 0 ){
                strcpy(names[txCnt], tempName);
                txCnt++;
            }
        }
    }
    Got everything to work until I discovered that
    Code:
    if( strcmp(state,"TX") ){
                strcpy(names[txCnt], tempName);
                txCnt++;
            }
    was letting all names thru, until I tried (strcmp(state,"TX")==0) then it let no one in.
    I am soo close to finishing this program, all of you have been such great help. I have learned a lot, I have only been learning C for the last 7 weeks

  10. #10
    Registered User camel-man's Avatar
    Join Date
    Jan 2011
    Location
    Under the moon
    Posts
    693
    Note what Jim said above.

    Fgets appends a newline character to the end of your string. So as of right now srtcmp(state,"TX") is not equaling zero like you think it is, because it's technically comparing "TX\n" with "TX" and giving you a number other than 0(indicating they don't match) which results in true.
    Code:
    int get_random_number(void)
    {
       return 4; //chosen by fair dice roll.
                 //guaranteed to be random
    }

  11. #11
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    I set strcmp to a var cmp and watched it evaluate and it ended up being 10 with TX\n. so it looks like I will have to use 10 as my test number.

  12. #12
    Registered User camel-man's Avatar
    Join Date
    Jan 2011
    Location
    Under the moon
    Posts
    693
    Strcmp works as so

    "This function return values that are as follows:

    if Return value < 0 then it indicates str1 is less than str2.


    if Return value > 0 then it indicates str2 is less than str1.


    if Return value = 0 then it indicates str1 is equal to str2

    "

    Meaning that the number it returns whether it's 10 or 230000, it doesn't matter it is indicating that they are not equal. You need to worry about checking to see if they're equal. The only time it will return 0 is when the two strings are equal. You need to trim the newline character off of State, or add in a newline character when comparing your "TX\n".

    A quick easy way to trim the newline is

    Code:
    state[strlen(state) - 1] = '\0';
    Then you can continue to compare as normal with ==0
    Last edited by camel-man; 11-19-2015 at 01:55 PM.
    Code:
    int get_random_number(void)
    {
       return 4; //chosen by fair dice roll.
                 //guaranteed to be random
    }

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,403
    Quote Originally Posted by camel-man
    A quick easy way to trim the newline is
    Code:
    state[strlen(state) - 1] = '\0';
    However, it is also wrong for the edge case where the string entered just fits into the destination array, excluding the newline. Therefore, a better solution would be:
    Code:
    state[strcspn(state, "\r\n")] = '\0';
    That said, this would be an incomplete solution as the newline that was not stored would remain in the input buffer, thereby resulting in incorrect input on the next iteration. Furthermore, the family member's name could well exceed 19 characters in length. If this is of concern, it would be better to use a loop to read a chunk, check if the newline exists, and if so, replace it with a null character and terminate the loop, otherwise read the next chunk, expanding the dynamic array, and keep looping.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    
    void freeMem(char **names, int size);
    float txFam(int size, float ageSum, char **names);
    
    
    int main() 
    {
        int fam_size=0;
        float sumAge=0;
        float aveAge=0.0;
        int i=0;
        int j=0;
        int k=0;
        char ch;
        
        /* generate array of strings the size of family */
        printf("How large is your Family: ");
        scanf("%d", &fam_size);
        ch = getchar();
        /* Allocate memory for 2d-array of strings */
        char **namesTx=malloc(fam_size*sizeof(char *));
        /* txFam returns sumAge to calculate aveAge */
        sumAge = txFam(fam_size, sumAge, namesTx);
        aveAge = (sumAge/fam_size);
        
        printf("The average age of the family is %.2f", aveAge);
        printf("\nFamily Members from Texas are: ");
        for(j=0; j<fam_size; j++)
            printf("\n%s", namesTx[j]);
            
        freeMem(namesTx, fam_size);
        getchar();
    }
    
    
    void freeMem(char **names, int size)
    {
        for(int k=0; k<size; k++) free(names[k]);
        free(names);
    }
    
    
    void printFam(char **names, int size)
    {
        
    }
    
    
    float txFam(int size, float ageSum, char **names)
    {
        int txCnt=0;
        float Age=0;
        char state[4];
        char tempName[20];
        int cmp=0;
        for(int k=0; k<size; k++){
            names[k]=malloc(20*sizeof(char *));
        }
        
        for(int i=0; i<size; i++){
            printf("\nEnter your family member's name: ");
            fgets(tempName, 20, stdin);
    
    
            printf("\nWhat state is s/he from? (use postal abbr) ");
            fgets(state, 4, stdin);
            
            printf("\nHow old? ");
            scanf("%f", &Age);
            ageSum += Age;
            
            getchar();
            getchar();
            
            /* saves names of family members from TX only */
            state[strlen(state)-1]="\0";
            cmp = strcmp(state,"TX");
            if( cmp == 0 ){
                strcpy(names[txCnt], tempName);
                txCnt++;
            }
        }
        return ageSum;
    }
    I am getting this message now:
    joshuarayfp.c: In function 'txFam':
    joshuarayfp.c:74:31: warning: assignment makes integer from pointer without a cast
    state[strlen(state)-1]="\0";
    Any ideas?

    Quote Originally Posted by camel-man View Post
    Strcmp works as so

    "This function return values that are as follows:

    if Return value < 0 then it indicates str1 is less than str2.


    if Return value > 0 then it indicates str2 is less than str1.


    if Return value = 0 then it indicates str1 is equal to str2

    "

    Meaning that the number it returns whether it's 10 or 230000, it doesn't matter it is indicating that they are not equal. You need to worry about checking to see if they're equal. The only time it will return 0 is when the two strings are equal. You need to trim the newline character off of State, or add in a newline character when comparing your "TX\n".

    A quick easy way to trim the newline is

    Code:
    state[strlen(state) - 1] = '\0';
    Then you can continue to compare as normal with ==0

  15. #15
    Registered User
    Join Date
    Nov 2015
    Posts
    9
    the 'state' string should be no more than 2 char long not including \0 and \n. the User should be using standard Postal Abbreviations for the States when requesting by the program.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. HELP!! College Assignment
    By college in forum C Programming
    Replies: 8
    Last Post: 03-22-2011, 06:53 AM
  2. Replies: 3
    Last Post: 04-26-2009, 08:54 AM
  3. Should I go to a state college and be 20k in debt, or a private college and be 90k in
    By Terrance in forum A Brief History of Cprogramming.com
    Replies: 10
    Last Post: 10-10-2003, 08:22 PM
  4. College or No College :: Future
    By kuphryn in forum A Brief History of Cprogramming.com
    Replies: 13
    Last Post: 09-25-2002, 03:48 PM
  5. How many of you are in college?
    By Fool in forum A Brief History of Cprogramming.com
    Replies: 22
    Last Post: 08-14-2001, 08:21 AM